import std.concurrency, std.stdio, std.process, std.file;
import std.c.time;

import Hpsdr.ozyUsb;
import Dsp.dspInterface;
import HttpServer.httpServer;
import WsServer.wsgui;
import Streaming.streaming;
import Definitions.msgCatalogue;
import Definitions.ozyConfig;
import Definitions.procNames;
import Registry.registry;


// Entry point of the SDR program
int main(char[][] args)
{
    // Start the main thread
    // Does not work when threads spawned from threads
    //inTid = spawn(&main_loop);
    main_loop();

    return 0;
}

// Main processing loop
void main_loop() {

    // Run the hpsdr processor
    // Pass in our Tid to receive samples
    // Get the transmitter Tid to send processed samples to

    if (open_hpsdr()) {
        writeln("Opened HPSDR device");
    }
    else {
        // Try loading the firmware
        writeln("Failed to open HPSDR device - loading firmware...");
        auto cwd = getcwd();
        chdir("../../../FirmwareLin");
        auto r = system("./initozy.sh");
        chdir(cwd);
        if(r == 0) {
            // Try again
            if (open_hpsdr()) {
                writeln("Opened HPSDR device");
            }
            else {
                writeln("Failed to open HPSDR device!");
                return;
            }
        }
        else {
            writeln("Failed to load firmware!");
            return;
        }
    }

    // Initialise modules
    Tid hpsdr_tid = init_hpsdr();
    Tid dsp_tid = init_dsp();
    Tid http_tid = init_http();
    Tid web_tid = init_web();
    Tid stream_tid = init_streaming();

    // Register our Tid
    CRegistry.register(E_PROC.MAIN, thisTid());
    CRegistry.register(E_PROC.HPSDR, hpsdr_tid);
    CRegistry.register(E_PROC.DSP, dsp_tid);
    CRegistry.register(E_PROC.HTTP, http_tid);
    CRegistry.register(E_PROC.WEB, web_tid);
    CRegistry.register(E_PROC.STREAM, stream_tid);

    // Configure the unit with some defaults
    hpsdr_tid.send(M_RATE(), E_SPEED.KHz48);
    hpsdr_tid.send(M_SRC_1(), E_CLOCK_LO_REF.Clk_10MHZ_Penelope);
    hpsdr_tid.send(M_SRC_2(), E_CLOCK_HI_REF.Clk_122MHZ_Penelope);
    hpsdr_tid.send(M_BOARD_CONFIG(), E_BOARD_CONFIG.Both_Present);
    hpsdr_tid.send(M_MIC_CONN(), E_MIC_SOURCE.Mic_Penelope);
    hpsdr_tid.send(M_SET_FREQ(), 7.0);

    // Sit in the receiver loop processing samples
    int count = 0;
    while (true) {
        //writeln("Entering main loop");
        receive(
            // Sample output processing
            (M_SMPLS_IN discriminator, immutable (float) [] smpls) {
                // Process
                //writeln("M_SMPLS_IN ", count++);
                //writeln("Got data ", smpls);
                // Process
                dsp_tid.send(M_SMPLS_TO_DSP(), smpls);
            },
            (M_SMPLS_FROM_DSP discriminator, immutable (float) [] smpls) {
                // Process
                //writeln("M_SMPLS_FROM_DSP", count);
                //writeln("Got data from DSP ", smpls);
                // Output
                hpsdr_tid.send(M_SMPLS_OUT(), smpls);
                stream_tid.send(M_SMPLS_OUT(), smpls);
            },
        );
    }
}
